package cn.com.gzheroli.core.interceptors;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.ibatis.jdbc.SQL;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.RedirectView;

import cn.com.gzheroli.bfw.pojo.base.TSUser;
import cn.com.gzheroli.cache.SpringRedisCache;
import cn.com.gzheroli.core.common.dao.jdbc.JdbcDao;
import cn.com.gzheroli.core.common.service.CommonService;
import cn.com.gzheroli.core.common.service.SystemService;
import cn.com.gzheroli.core.manager.Client;
import cn.com.gzheroli.core.util.ContextHolderUtils;
import cn.com.gzheroli.core.util.DataUtils;
import cn.com.gzheroli.core.util.ResourceUtil;
import cn.com.gzheroli.core.util.oConvertUtils;


/**
 * 权限拦截器
 * 
 * 
 */
public class AuthInterceptor implements HandlerInterceptor {
	 
	private static final Logger logger = Logger.getLogger(AuthInterceptor.class);
	private List<String> excludeUrls;
	private List<String> serviceUrls;
	@Autowired
	private SystemService systemService;
	@Autowired
	private CommonService commonService;
	@Autowired
	private JdbcDao jdbcDao;
	@Autowired
    private SpringRedisCache cache;
	public List<String> getExcludeUrls() {
		return excludeUrls;
	}

	public void setExcludeUrls(List<String> excludeUrls) {
		this.excludeUrls = excludeUrls;
	}


	/**
	 * 在controller后拦截
	 */
	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object object, Exception exception) throws Exception {
	}
	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object object, ModelAndView modelAndView) throws Exception {

	}
	public boolean checkIgnoreUrl(String requestPath){
		for (String serviceUrl : serviceUrls) {
			if (requestPath.indexOf(serviceUrl) >-1) {
				return true;
			}
		}
		for (String excludeUrls : excludeUrls) {
			if (requestPath.indexOf(excludeUrls) >-1) {
				return true;
			}
		}
		return false;
	}
	/**
	 * 在controller前拦截
	 */
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object)  {
		String requestPath = ResourceUtil.getRequestPath(request);// 用户访问的资源地址
		/*if (excludeUrls.contains(requestPath)||requestPath.startsWith("file/")||requestPath.startsWith("api/test/tt.do")) {
			return true;
		}else */if(checkIgnoreUrl(requestPath)||requestPath.startsWith("file/")){
			return true;
		}else {
			
			String token = request.getHeader("token")==null?request.getParameter("token"):request.getHeader("token");
			if(token==null||token.trim().equals("")){
				response.setStatus(401);
				return false;	
			}
	        System.out.println(token);
	        Client client=null;
	        try{
			 client=cache.getCache(token, Client.class);
	        }catch(Exception e){
	        	cache.deleteCache(token);
	        }
			if(client == null){ 
				response.setStatus(401);
				return false;
			}
			
			//更新session超期时间
			if (cache.containsKey(token)) {
				Long time = cache.getExpireTime(token);
				//0:pc app:手机
				String clientType = request.getHeader("clientType")==null?"pc": request.getHeader("clientType");
				if(clientType==null||clientType.trim().equals("pc")||clientType.trim().equals("")) {
			    	cache.putCacheWithExpireTime(token, client,30*60);
					//cache.setObjExpireTime(token,30*60);
				}else if(clientType.trim().equals("app")){
			    	cache.putCacheWithExpireTime(token, client,30*24*60*60);
			    	//cache.setObjExpireTime(token,30*24*60*60);
			    }else{
			    	cache.putCacheWithExpireTime(token, client,10*24*60*60);
			    	//cache.setObjExpireTime(token,10*24*60*60);
			    }
				// long time1 = Long.parseLong(time + "0000000");
				// Date date = new Date(time);
				System.out.println(clientType+"   session超期时间："+DataUtils.formatDate(new Date(time), "yyyy-MM-dd HH:mm:ss"));
			}	
			if (client != null && client.getUser()!=null ) {
				//if(requestPath.startsWith("api/"))
				if (serviceUrls != null && serviceUrls.size() > 0) {
					for (String serviceUrl : serviceUrls) {
						if (requestPath.indexOf(serviceUrl) == 0) {
							return true;
						}
					}
				}
				 if(!hasMenuAuth(request,token)){
					// response.sendRedirect("loginController.do?noAuth");
					//request.getRequestDispatcher("webpage/common/noAuth.jsp").forward(request, response);
					 response.setStatus(403);
					return false;
				}
				String functionId=oConvertUtils.getString(request.getParameter("clickFunctionId"));
				if(!oConvertUtils.isEmpty(functionId)){//从菜单点击进入的页面
					Set<String> operationCodes = systemService.getOperationCodesByUserIdAndFunctionId(client.getUser().getId(), functionId);
					request.setAttribute("operationCodes", operationCodes);//设置权限操作代码
				 
				}else{//如果是从具体页面打开的页面	
					functionId = systemService.getFunctionIdByFunctionUrl(requestPath);
					if(!oConvertUtils.isEmpty(functionId)){
						Set<String> operationCodes = systemService.getOperationCodesByUserIdAndFunctionId(client.getUser().getId(), functionId);
						request.setAttribute("operationCodes", operationCodes);//设置权限操作代码
					}
				}
				if(!oConvertUtils.isEmpty(functionId)){
					//获取所有操作代码
					Map para1=new HashMap();
					para1.put("functionId", functionId);
					String sql1="select operation_code from T_S_OPERATION where FUNCTION_ID=#{functionId}";
					List<String> allOperation=this.commonService.getStringListBySql(sql1,para1); 
					  
					List<String> newall = new ArrayList<String>();
					if(allOperation.size()>0){
						for(String s:allOperation){ 
						    s=s.replaceAll(" ", "");
							newall.add(s); 
						}
						//去除有权限操作的代码
						String hasOperSql="SELECT operation FROM T_S_ROLE_FUNCTION fun, T_S_ROLE_USER role WHERE  " +
							"fun.function_id='"+functionId+"' AND fun.operation!=''  AND fun.role_id=role.role_id AND role.user_id='"+client.getUser().getId()+"' ";
						Map para=new HashMap();
						para.put("functionId", functionId);
						para.put("userId", client.getUser().getId());
						String sql="select fun.operation from T_S_ROLE_FUNCTION fun,T_S_ROLE_USER role where fun.operation!=''  AND fun.role_id=role.role_id ";
						sql=sql+" and fun.function_id=#{pTypeGroupCode} and role.user_id==#{ptypecode}";
						List<String> hasOperList = this.commonService.getStringListBySql(sql,para); 
					    for(String strs:hasOperList){
							    for(String s:strs.split(",")){
							        s=s.replaceAll(" ", "");
							    	newall.remove(s);
							    } 
						} 
					}
					 request.setAttribute("noauto_operationCodes", newall);//设置所有没有权限操作的代码
				}
				return true;
			} else {
				response.setStatus(401);
				return false;
			}

		}
	}
	private boolean hasMenuAuth(HttpServletRequest request,String token){
		String requestPath = ResourceUtil.getRequestPath(request);// 用户访问的资源地址
		// 是否是功能表中管理的url
		boolean bMgrUrl = false;
		TSUser user =cache.getCache(token, Client.class).getUser();
		String functionId = systemService.getFunctionIdByFunctionUrl(requestPath);
		if(functionId!=null&&!functionId.equals("")) {
			bMgrUrl=true;
		}
		if (!bMgrUrl) {
			return true;
		}
		 
		String funcid=oConvertUtils.getString(request.getParameter("clickFunctionId"));
		if(!bMgrUrl && (requestPath.indexOf("loginController.do")!=-1||funcid.length()==0)){
			return true;
		} 
		
		String userid =user.getId();
		Map para=new HashMap();
		para.put("userid", userid);
		SQL sql=new SQL();
		sql.SELECT("count(DISTINCT f.id)");
		sql.FROM("T_S_FUNCTION f");
		sql.FROM("T_S_ROLE_FUNCTION  rf");
		sql.FROM("T_S_ROLE_USER ru");
		sql.WHERE("f.id=rf.function_id AND rf.role_id=ru.role_id");
		sql.WHERE("ru.user_id=#{userid}");
		sql.WHERE("f.function_url like '"+requestPath+"%'");
		Long listSize = this.commonService.getCountForJdbc(sql.toString(),para);
		if(listSize.intValue()==0){
			return false;
		}else{
			return true;
		}
	}
	/**
	 * 转发
	 * 
	 * @param user
	 * @param req
	 * @return
	 */
	@RequestMapping(params = "forword")
	public ModelAndView forword(HttpServletRequest request) {
		return new ModelAndView(new RedirectView("loginController.do?login"));
	}

	private void forward(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//		request.getRequestDispatcher("webpage/login/timeout.jsp").forward(request, response);
		response.setStatus(403);
	}

	public List<String> getServiceUrls() {
		return serviceUrls;
	}

	public void setServiceUrls(List<String> serviceUrls) {
		this.serviceUrls = serviceUrls;
	}

}

